package com.swlz.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.math.BigDecimal;
import java.sql.SQLException;

import com.swlz.dao.MallAddressDAO;
import com.swlz.dao.MallCartDAO;
import com.swlz.dao.MallOrderDAO;
import com.swlz.dao.MallOrderDetailDAO;
import com.swlz.dao.MallProductDAO;
import com.swlz.dto.MallCartDTO;
import com.swlz.entity.MallAddress;
import com.swlz.entity.MallCart;
import com.swlz.entity.MallOrder;
import com.swlz.entity.MallOrderDetail;
import com.swlz.exception.CodeException;
import com.swlz.service.MallCartService;
import com.swlz.vo.MallCartVO;
import com.swlz.vo.PageVO;

import cn.hutool.core.util.ObjectUtil;

/**
 * <pre>
 * 业务逻辑接口具体实现类
 * 商城购物车
 * ClassName : com.swlz.service.impl.MallCartServiceImpl
 * Author : swlz
 * E-Mail : 2233875735@qq.com
 * Date : 2020-07-02 17:55:47
 * Version : 1.0
 * Copyright 2020 swlz.top Inc. All rights reserved. 
 * Warning: this content is only for internal circulation of the company. It is forbidden to divulge it or use it for other commercial purposes
 * </pre>
 **/
public class MallCartServiceImpl implements MallCartService {
	private static Logger log = LoggerFactory.getLogger(MallCartServiceImpl.class);

	private MallCartDAO mallCartDAO = new MallCartDAO();

	private MallProductDAO mallProductDAO = new MallProductDAO();
	private MallAddressDAO mallAddressDAO = new MallAddressDAO();
	private MallOrderDAO mallOrderDAO = new MallOrderDAO();
	private MallOrderDetailDAO mallOrderDetailDAO = new MallOrderDetailDAO();

	@Override
	public int add(MallCart mallCart) throws CodeException {
		try {
			MallCart mallCart1 = mallCartDAO.selectByModel(mallCart);
			mallCart1.setCartNum(mallCart1.getCartNum() + 1);
			mallCart1.setCartTime(new Date());
			return mallCartDAO.update(mallCart1);
		} catch (SQLException e) {
			mallCart.setCartNum(1);
			mallCart.setCartTime(new Date());
			try {
				return mallCartDAO.insert(mallCart);
			} catch (SQLException e1) {
				throw new CodeException(500, "将商品添加到购物车失败！");
			}

		}
	}

	@Override
	public int update(MallCart mallCart) throws CodeException {
		try {
			return mallCartDAO.updateSelective(mallCart);
		} catch (SQLException e) {
			log.warn("修改商城购物车错误", e);
			throw new CodeException(501, "修改商城购物车错误", e);
		}
	}

	@Override
	public int delete(Long cartId) throws CodeException {
		try {
			return mallCartDAO.deleteById(cartId);
		} catch (SQLException e) {
			log.warn("删除商城购物车错误", e);
			throw new CodeException(502, "删除商城购物车错误", e);
		}
	}

	@Override
	public MallCart get(Long cartId) throws CodeException {
		try {
			return mallCartDAO.selectById(cartId);
		} catch (SQLException e) {
			log.warn("获取商城购物车失败", e);
			throw new CodeException(503, "获取商城购物车失败", e);
		}
	}

	@Override
	public PageVO<MallCart> page(MallCart mallCart, Integer current, Integer rowMax) throws CodeException {
		try {
			long total = mallCartDAO.countByModel(mallCart);
			PageVO<MallCart> page = new PageVO<>(total, current, rowMax);
			return page.setList(mallCartDAO.selectByModel(mallCart, page.getOffset(), page.getRowMax()));
		} catch (SQLException e) {
			log.warn("获取商城购物车分页数据失败", e);
			throw new CodeException(504, "获取商城购物车分页数据失败", e);
		}
	}

	@Override
	public List<MallCart> list(MallCart mallCart, int len) {
		try {
			return mallCartDAO.selectByModel(mallCart, 0, len);
		} catch (SQLException e) {
			log.warn("获取商城购物车列表数据失败", e);
			throw new CodeException(505, "获取商城购物车列表数据失败", e);
		}
	}

	@Override
	public List<MallCartVO> list(Long userId) {
		try {
			return mallCartDAO.selectByUserId(userId);
		} catch (SQLException e) {
			log.warn("获取商城购物车列表数据失败", e);
			throw new CodeException(505, "获取商城购物车列表数据失败", e);
		}
	}

	@Override
	public MallOrder addOrder(MallCartDTO dto) {

		if (dto.getUserId() == null) {
			throw new CodeException(401, "用户未登录");
		}

		if (dto.getAddressId() == null) {
			throw new CodeException(1000, "地址不能为空");
		}

		if (ObjectUtil.hasEmpty(dto.getProductId(), dto.getCartNum())) {
			throw new CodeException(1000, "购买的商品不能为空");
		}

		if (dto.getProductId().size() != dto.getCartNum().size()) {
			throw new CodeException(1001, "购买的商品数量不一致");
		}

		// 1.获取购买的商品的基本信息
		// 一个一个的查找？效率很低
		// 建议：一次性全部查找，只返回需要的字段[属性]
		Map<Long, Float> products = null;
		try {
			products = mallProductDAO.selectPrice(dto.getProductId());
		} catch (Exception ex) {
			throw new CodeException(1002, "获取商品的价格出错", ex);
		}

		if (products.size() != dto.getProductId().size()) {
			throw new CodeException(1002, "获取商品的价格出错");
		}

		// 2.计算总金额
		// 最好从前台获取总金额，并和计算后的对比，如果不一致，则提示报错
		float count = 0f; // 总金额
		for (int i = 0; i < dto.getProductId().size(); i++) {
			Long productId = dto.getProductId().get(i);
			Integer num = dto.getCartNum().get(i);
			count += products.get(productId) * num;
		}

		// 3.查找收货信息
		MallAddress mallAddress = null;
		try {
			mallAddress = mallAddressDAO.selectById(dto.getAddressId());
		} catch (Exception ex) {
			throw new CodeException(1003, "获取收货地址出错", ex);
		}

		// 4.(选做)减去对应的商品库存（update）

		// 5.添加订单（订单号，用户编号，收货相关，订单创建时间，订单实付金额，订单客户说明，订单状态0）
		MallOrder order = new MallOrder();
		// order.setOrderId(orderId);//dao中会自动设置雪花数
		order.setUserId(dto.getUserId());
		order.setOrderAddressCode(mallAddress.getAddressCode());
		order.setOrderAddressInfo(mallAddress.getAddressInfo());
		order.setOrderAddressName(mallAddress.getAddressName());
		order.setOrderAddressTel(mallAddress.getAddressTel());
		order.setOrderAddressZip(mallAddress.getAddressZip());
		order.setOrderTime(new Date());
		order.setOrderMoney(count);
		order.setOrderMemo(dto.getOrderMemo());
		order.setOrderPayTime(new Date());//发起支付的时间
		order.setOrderStatus(0);
		try {
			mallOrderDAO.insertSelective(order);
		} catch (Exception ex) {
			throw new CodeException(1004, "添加订单失败", ex);
		}

		// 6.添加订单详情
		for (int i = 0; i < dto.getProductId().size(); i++) {
			MallOrderDetail detail = new MallOrderDetail();
			Long productId = dto.getProductId().get(i);
			Integer num = dto.getCartNum().get(i);
			detail.setOrderDetailMoney(products.get(productId));
			detail.setOrderDetailNum(num);
			detail.setOrderId(order.getOrderId());
			detail.setProductId(productId);
			try {
				mallOrderDetailDAO.insert(detail);
			} catch (Exception ex) {
				throw new CodeException(1005, "添加订单详情失败", ex);
			}
		}

		// 7.删除该用户购物车中的已购买产品
		try {
			mallCartDAO.delete(dto.getUserId(), dto.getProductId());
		} catch (Exception ex) {
			throw new CodeException(1006, "删除购物车中的商品失败", ex);
		}

		// 4.5.6.7.操作要具有一致性，要么都成功，只要有一个失败，所有操作数据库不受影响，事务
		return order;
	}

}
